﻿namespace NetFx.SMIL
{
  using System;
  using System.Text;
  using System.Collections;
  using System.Collections.Generic;
  using System.Reflection;
  using System.Reflection.Emit;
  using NetFx.AGIL;
  using NetFx.SMIL.References;

  /// <summary>
  /// Smil 操作。
  /// </summary>
  public class SmilOperation
  {

    #region Opcodes 56

    public static readonly SmilOperation Try;
    public static readonly SmilOperation TryEnd;
    public static readonly SmilOperation Filter;
    public static readonly SmilOperation Catch;
    public static readonly SmilOperation Fault;
    public static readonly SmilOperation Finally;

    public static readonly SmilOperation Mark;
    public static readonly SmilOperation And;
    public static readonly SmilOperation Pause;
    public static readonly SmilOperation Given;
    public static readonly SmilOperation Address;
    public static readonly SmilOperation Arguments;
    public static readonly SmilOperation JotIn;
    public static readonly SmilOperation Double;
    public static readonly SmilOperation Discard;
    public static readonly SmilOperation Execute;
    public static readonly SmilOperation Cause;
    public static readonly SmilOperation Perform;
    public static readonly SmilOperation Apart;
    public static readonly SmilOperation Dap;
    public static readonly SmilOperation Return;
    public static readonly SmilOperation Divert;
    public static readonly SmilOperation Switch;
    public static readonly SmilOperation Figure;
    public static readonly SmilOperation Fetch;
    public static readonly SmilOperation Send;
    public static readonly SmilOperation FillAs;
    public static readonly SmilOperation Measure;
    public static readonly SmilOperation Reset;
    public static readonly SmilOperation Shape;
    public static readonly SmilOperation TellIf;
    public static readonly SmilOperation Cast;
    public static readonly SmilOperation Array;
    public static readonly SmilOperation Enumerate;
    public static readonly SmilOperation Pack;
    public static readonly SmilOperation Unpack;
    public static readonly SmilOperation Convert;
    public static readonly SmilOperation Pick;
    public static readonly SmilOperation Plug;
    public static readonly SmilOperation Locate;
    public static readonly SmilOperation Throw;
    public static readonly SmilOperation Rethrow;
    public static readonly SmilOperation SeeIf;
    public static readonly SmilOperation AssertFinite;
    public static readonly SmilOperation Allocate;
    public static readonly SmilOperation Volatile;
    public static readonly SmilOperation Unaligned;
    public static readonly SmilOperation Copy;
    public static readonly SmilOperation Clear;
    public static readonly SmilOperation GivenRef;
    public static readonly SmilOperation GivenType;
    public static readonly SmilOperation AddressRef;
    public static readonly SmilOperation Prefix;
    public static readonly SmilOperation FilterEnd;
    public static readonly SmilOperation FinallyEnd;
    public static readonly SmilOperation GoFor;
    #endregion
    #region Opcodes definitons

    public static readonly SmilOperation[] AllSmilOpcodes;

    static SmilOperation()
    {
      AllSmilOpcodes = new SmilOperation[]
      {
        #region Mark
         Mark  = SmilOperation.of("Mark",     null),
        #endregion
        #region Try
         Try    = SmilOperation.of("Try",      AgilOperation.Try,    null),
        #endregion
        #region TryEnd
         TryEnd = SmilOperation.of("TryEnd",   AgilOperation.TryEnd, null),
        #endregion
        #region Filter
         Filter = SmilOperation.of("Filter",   AgilOperation.Filter, null),
        #endregion
        #region Catch
         Catch  = SmilOperation.of("Catch",    AgilOperation.Catch,  null),
        #endregion
        #region Fault
         Fault  = SmilOperation.of("Fault",    AgilOperation.Fault,  null),
        #endregion
        #region Finally
         Finally= SmilOperation.of("Finally",  AgilOperation.Finally,null),
        #endregion
        #region And
        /// 如果修补操作码，则填充空间。尽管可能消耗处理周期，但未执行任何有意义的操作。
        And                = SmilOperation.of("And",
                                AgilOperation.Nop,      null    //0: Hint for Nop
                              ),
        #endregion
        #region Pause
        /// 向公共语言结构 (CLI) 发出信号以通知调试器已撞上了一个断点。
        Pause               = SmilOperation.of("Pause",
                                AgilOperation.Break,    null    //0:  Hint for Break
                              ),
        #endregion
        #region Given
        /// 将值加载到计算栈上。
        Given               = SmilOperation.of("Given",
                                AgilOperation.Ldc_I4_M1,
                                AgilOperation.Ldc_I4_0,
                                AgilOperation.Ldc_I4_1,
                                AgilOperation.Ldc_I4_2,
                                AgilOperation.Ldc_I4_3,
                                AgilOperation.Ldc_I4_4,
                                AgilOperation.Ldc_I4_5,
                                AgilOperation.Ldc_I4_6,
                                AgilOperation.Ldc_I4_7,
                                AgilOperation.Ldc_I4_8, null,   //0:  Hint for encoded consts.
                                AgilOperation.Ldc_I4_S,
                                AgilOperation.Ldc_I4,
                                AgilOperation.Ldc_I8,   null,   //1:  Hint for int consts
                                AgilOperation.Ldc_R4,
                                AgilOperation.Ldc_R8,   null,   //2:  Hint for real consts.
                                AgilOperation.Ldarg_0,
                                AgilOperation.Ldarg_1,
                                AgilOperation.Ldarg_2,
                                AgilOperation.Ldarg_3,  null,   //3:  Hint for encoded arguments.
                                AgilOperation.Ldarg_S,
                                AgilOperation.Ldarg,    null,   //4:  Hint for other arguments.
                                AgilOperation.Ldloc_0,
                                AgilOperation.Ldloc_1,
                                AgilOperation.Ldloc_2,
                                AgilOperation.Ldloc_3,  null,   //5:  Hint for encoded locals
                                AgilOperation.Ldloc_S,
                                AgilOperation.Ldloc,    null,   //6:  Hint for other locals
                                AgilOperation.Ldsfld,   null,   //7:  Hint for static field
                                AgilOperation.Ldnull,   null,   //9:  Hint for null literal
                                AgilOperation.Ldstr,    null,   //10: Hint for string literal
                                AgilOperation.Ldtoken,  null,   //11: Hint for token
                                AgilOperation.Ldftn,    null,   //0:Hint for ldftn
                                AgilOperation.Ldfld,    null,   //8:  Hint for instance field
                                AgilOperation.Ldvirtftn,null    //0:Hint for ldvirtftn
                        ),
        #endregion
        #region Address (Address: given the address of)
        /// 将地址加载到计算栈上。
        Address              = SmilOperation.of("Address",
                                AgilOperation.Ldarga,
                                AgilOperation.Ldarga_S, null,   //0:  Hint for argument addresses
                                AgilOperation.Ldloca,
                                AgilOperation.Ldloca_S, null,   //1:  Hint for local addresses
                                AgilOperation.Ldsflda,  null,   //2:  Hint for static field addresses
                                AgilOperation.Ldflda,   null    //3:  Hint for instance field address
                              ),
        #endregion
        #region Arguments (Arguments: given the address of arguments)
        /// 返回指向当前方法的参数列表的非托管指针。
        Arguments       = SmilOperation.of("Arguments",
                                AgilOperation.Arglist,  null    //0:  Hint for argument list
                              ),
        #endregion
        #region JotIn
        /// 将值从计算栈存储到指定的位置。
        JotIn               = SmilOperation.of("JotIn",
                                AgilOperation.Stloc_0,
                                AgilOperation.Stloc_1,
                                AgilOperation.Stloc_2,
                                AgilOperation.Stloc_3,  null,   //0:  Hint for encoded locals
                                AgilOperation.Stloc_S,
                                AgilOperation.Stloc,    null,   //1:  Hint for other locals
                                AgilOperation.Starg,
                                AgilOperation.Starg_S,  null,   //2:  Hint for arguments
                                AgilOperation.Stsfld,   null,   //3:  Hint for static fields
                                AgilOperation.Stfld,    null    //4:  Hint for instance fields
                              ),
        #endregion
        #region Double
        /// 复制计算堆栈上当前最顶端的值，然后将副本推送到计算堆栈上
        Double              = SmilOperation.of("Double",
                                AgilOperation.Dup,      null    //0:  Hint for dup
                              ),
        #endregion
        #region Discard
        /// 移除当前位于计算堆栈顶部的值。
        Discard             = SmilOperation.of("Discard",
                                AgilOperation.Pop,      null    //0:  Hint for pop
                              ),
        #endregion
        #region Execute (Execute: action related)
        /// 调用由传递的方法说明符指示的方法。
        Execute             = SmilOperation.of("Execute",
                                AgilOperation.Call,     null    //0:  Hint for call
                              ),
        #endregion
        #region Perform (Perform: role related)
        /// 对对象调用后期绑定方法，并且将返回值推送到计算堆栈上。
        Perform            = SmilOperation.of("Perform",
                                AgilOperation.Callvirt, null    //0:  Hint for callvirt
                              ),
        #endregion
        #region Apart (Apart: never return)
        /// 执行后缀的方法调用指令，以便在执行实际调用指令前移除当前方法的堆栈帧。
        Apart            = SmilOperation.of("Apart",
                                AgilOperation.Tailcall, null    //0:  Hint for tailcall
                              ),
        #endregion 
        #region Cause (Cause: let others make it execute)
        /// 通过调用约定描述的参数调用在计算堆栈上指示的方法（作为指向入口点的指针）。
        Cause              = SmilOperation.of("Cause",
                                AgilOperation.Calli,    null    //0:  Hint for calli
                              ),
        #endregion
        #region Dap
        /// 退出当前方法并跳至指定方法。
        Dap                 = SmilOperation.of("Dap",
                                AgilOperation.Jmp,      null    //0:  Hint for jump
                              ),
        #endregion
        #region Return
        /// 从当前方法返回，并将返回值（如果存在）从调用方的计算堆栈推送到被调用方的计算堆栈上。
        Return              = SmilOperation.of("Return",
                                AgilOperation.Ret,      null    //0:  Hint for ret
                              ),
        #endregion
        #region Divert
        /// 当条件成立的时候转移
        Divert              = SmilOperation.of("Divert",
                                AgilOperation.Beq,
                                AgilOperation.Beq_S,
                                AgilOperation.Bge,
                                AgilOperation.Bge_S,
                                AgilOperation.Bgt,
                                AgilOperation.Bgt_S,
                                AgilOperation.Ble,
                                AgilOperation.Ble_S,
                                AgilOperation.Blt,
                                AgilOperation.Blt_S,            //0:  Hint for signed cond branching
                                AgilOperation.Bne_Un,
                                AgilOperation.Bne_Un_S,
                                AgilOperation.Bge_Un,
                                AgilOperation.Bge_Un_S,
                                AgilOperation.Bgt_Un,
                                AgilOperation.Bgt_Un_S,
                                AgilOperation.Ble_Un,
                                AgilOperation.Ble_Un_S,
                                AgilOperation.Blt_Un,   
                                AgilOperation.Blt_Un_S,         //1:  Hint for unsigned cond branching
                                AgilOperation.Brfalse,
                                AgilOperation.Brfalse_S,        //2:  Hint for false branching
                                AgilOperation.Brtrue,
                                AgilOperation.Brtrue_S,         //3:  Hint for true branching
                                AgilOperation.Br,
                                AgilOperation.Br_S,      null   //4:  Hint for uncond branching
                              ),
        #endregion
        #region Switch
        /// 返回指向当前方法的参数列表的非托管指针。
        Switch              = SmilOperation.of("Switch",
                                AgilOperation.Switch,   null    //0:  Hint for switch
                              ),
        #endregion
        #region Fetch
        /// 将值间接加载到计算栈上。
        Fetch        = SmilOperation.of("Fetch",
                                AgilOperation.Ldind_Ref,null,   //0:  Hint for ref loading
                                AgilOperation.Ldind_I,  null,   //1:  Hint for ldind_native_int
                                AgilOperation.Ldind_I1,
                                AgilOperation.Ldind_I2,
                                AgilOperation.Ldind_I4,
                                AgilOperation.Ldind_I8, null,   //2:  Hint for ldind_int
                                AgilOperation.Ldind_U1,
                                AgilOperation.Ldind_U2,
                                AgilOperation.Ldind_U4, null,   //3:  Hint for ldind_uint
                                AgilOperation.Ldind_R4, 
                                AgilOperation.Ldind_R8, null,   //4:  Hint for ldind_real
                                AgilOperation.Ldobj,    null     //0:  Hint for ldobj
                              ),
        #endregion
        #region Send
        /// 在所提供的地址存储指定类型的值
        Send       = SmilOperation.of("Send",
                                AgilOperation.Stind_Ref,null,   //0:  Hint for ref stroing
                                AgilOperation.Stind_I,  null,   //1:  Hint for stind_native_int
                                AgilOperation.Stind_I1,
                                AgilOperation.Stind_I2,
                                AgilOperation.Stind_I4,
                                AgilOperation.Stind_I8, null,   //2:  Hint for stind_int
                                AgilOperation.Stind_I1,
                                AgilOperation.Stind_I2,
                                AgilOperation.Stind_I4,
                                AgilOperation.Stind_I8, null,   //3:  Hint for stind_uint (int simulated)
                                AgilOperation.Stind_R4,
                                AgilOperation.Stind_R8, null,   //4:  Hint for stind_real
                                AgilOperation.Stobj,    null    //0:  Hint for stobj
                              ),
        #endregion
        #region Figure
        /// 对两个给定值进行二元运算。
        Figure                 = SmilOperation.of("Figure",
                                AgilOperation.Neg,              
                                AgilOperation.Add,
                                AgilOperation.Add_Ovf,
                                AgilOperation.Add_Ovf_Un,       
                                AgilOperation.Sub,
                                AgilOperation.Sub_Ovf,
                                AgilOperation.Sub_Ovf_Un,       
                                AgilOperation.Mul,
                                AgilOperation.Mul_Ovf,
                                AgilOperation.Mul_Ovf_Un,       
                                AgilOperation.Div,
                                AgilOperation.Div_Un,           
                                AgilOperation.Rem,
                                AgilOperation.Rem_Un,           
                                AgilOperation.Not,              
                                AgilOperation.And,              
                                AgilOperation.Or,               
                                AgilOperation.Xor,              
                                AgilOperation.Shl,              
                                AgilOperation.Shr,
                                AgilOperation.Shr_Un,     null 
                              ),
        #endregion
        #region FillAs
        /// 将位于对象（&、* 或 natural int 类型）地址的值类型复制到目标对象（&、* 或 natural int 类型）的地址。
        FillAs       = SmilOperation.of("FillAs",
                                AgilOperation.Cpobj,      null  //0:  Hint for cpobj
                              ),
        #endregion
        #region Measure
        /// 将提供的值类型的大小（以字节为单位）推送到计算堆栈上。
        Measure             = SmilOperation.of("Measure",
                                AgilOperation.Sizeof,     null  //0:  Hint for sizeof
                              ),
        #endregion
        #region Reset
        /// 将位于指定地址的对象的所有字段初始化为空引用或适当的基元类型的 0。
        Reset   = SmilOperation.of("Reset",
                                AgilOperation.Initobj,    null  //0:  Hint for initobj
                              ),
        #endregion
        #region Shape
        /// 创建一个值类型的新对象或新实例，并将对象引用（O 类型）推送到计算堆栈上。
        Shape               = SmilOperation.of("Shape",
                                AgilOperation.Newobj,     null  //0:  Hint for newobj
                              ),
        #endregion
        #region TellIf
        /// 测试对象引用（O 类型）是否为特定类的实例。
        TellIf          = SmilOperation.of("TellIf",
                                AgilOperation.Isinst,     null  //0:  Hint for isinst
                              ),
        #endregion
        #region Cast
        /// 尝试将引用传递的对象转换为指定的类。
        Cast                = SmilOperation.of("Cast",
                                AgilOperation.Castclass,  null  //0:  Hint for castclass
                              ),
        #endregion
        #region Array
        /// 将对新的从零开始的一维数组（其元素属于特定类型）的对象引用推送到计算堆栈上。
        Array              = SmilOperation.of("Array",
                                AgilOperation.Newarr,     null  //0:  Hint for newarr
                              ),
        #endregion
        #region Enumerate
        /// 将从零开始的、一维数组的元素的数目推送到计算堆栈上。
        Enumerate          = SmilOperation.of("Enumerate",
                                AgilOperation.Ldlen,      null  //0:  Hint for ldlen
                              ),
        #endregion 
        #region Pack
        /// 将值类转换为对象引用（O 类型）。
        Pack                = SmilOperation.of("Pack",
                                AgilOperation.Box,        null  //0:  Hint for box
                              ),
        #endregion
        #region Unpack
        /// 将值类型的已装箱的表示形式转换为其未装箱的形式。
        Unpack              = SmilOperation.of("Unpack",
                                AgilOperation.Unbox,      null, //0:  Hint for unbox
                                AgilOperation.Unbox_Any,  null  //0:  Hint for unbox_any
                              ),
        #endregion
        #region Convert
        /// 转换位于计算堆栈顶部的值到指定类型。
        Convert             = SmilOperation.of("Convert",
                                AgilOperation.Conv_I,
                                AgilOperation.Conv_Ovf_I,
                                AgilOperation.Conv_Ovf_I_Un,null, //0:  Hint for native int
                                AgilOperation.Conv_U,
                                AgilOperation.Conv_Ovf_U,
                                AgilOperation.Conv_Ovf_U_Un,null, //1:  Hint for native uint
                                AgilOperation.Conv_I1,
                                AgilOperation.Conv_Ovf_I1,
                                AgilOperation.Conv_Ovf_I1_Un,null,//2:  Hint for I1
                                AgilOperation.Conv_I2,
                                AgilOperation.Conv_Ovf_I2,
                                AgilOperation.Conv_Ovf_I2_Un,null,//3:  Hint for I2
                                AgilOperation.Conv_I4,
                                AgilOperation.Conv_Ovf_I4,
                                AgilOperation.Conv_Ovf_I4_Un,null,//4:  Hint for I4
                                AgilOperation.Conv_I8,
                                AgilOperation.Conv_Ovf_I8,
                                AgilOperation.Conv_Ovf_I8_Un,null,//5:  Hint for I8
                                AgilOperation.Conv_U1,
                                AgilOperation.Conv_Ovf_U1,
                                AgilOperation.Conv_Ovf_U1_Un,null,//6:  Hint for U1
                                AgilOperation.Conv_U2,
                                AgilOperation.Conv_Ovf_U2,
                                AgilOperation.Conv_Ovf_U2_Un,null,//7:  Hint for U2
                                AgilOperation.Conv_U4,
                                AgilOperation.Conv_Ovf_U4,
                                AgilOperation.Conv_Ovf_U4_Un,null,//8:  Hint for U4
                                AgilOperation.Conv_U8,
                                AgilOperation.Conv_Ovf_U8,
                                AgilOperation.Conv_Ovf_U8_Un,null,//9:  Hint for U8
                                AgilOperation.Conv_R_Un,     null,//10: Hint for native real
                                AgilOperation.Conv_R4,       null,//11: Hint for real4
                                AgilOperation.Conv_R8,       null //12: Hint for real8

                              ),
        #endregion
        #region Pick
        /// 从数组的指定下标上取出元素。
        Pick                = SmilOperation.of("Pick",
                                AgilOperation.Ldelem_Any,   null, //0:Hint for ldelem_any
                                AgilOperation.Ldelem_Ref,   null, //1:Hint for ldelem_ref
                                AgilOperation.Ldelem_I,     null, //2:Hint for ldelem_native_int
                                AgilOperation.Ldelem_I1,
                                AgilOperation.Ldelem_I2,
                                AgilOperation.Ldelem_I4,
                                AgilOperation.Ldelem_I8,    null, //3:Hint for ldelem_int
                                AgilOperation.Ldelem_U1,
                                AgilOperation.Ldelem_U2,
                                AgilOperation.Ldelem_U4,    
                                AgilOperation.Ldelem_I8,    null, //4:Hint for ldelem_uint (I8 simulated U8)
                                AgilOperation.Ldelem_R4,
                                AgilOperation.Ldelem_R8,    null  //5:Hint for ldelem_real
                              ),
        #endregion
        #region Plug
        /// 向数组的指定位置上存储元素。
        Plug                = SmilOperation.of("Plug",
                                AgilOperation.Stelem_Any,   null, //0:Hint for stelem_any
                                AgilOperation.Stelem_Ref,   null, //1:Hint for stelem_ref
                                AgilOperation.Stelem_I,     null, //2:Hint for stelem_native_int
                                AgilOperation.Stelem_I1,
                                AgilOperation.Stelem_I2,
                                AgilOperation.Stelem_I4,
                                AgilOperation.Stelem_I8,    null, //3:Hint for stelem_int
                                AgilOperation.Stelem_I1,
                                AgilOperation.Stelem_I2,
                                AgilOperation.Stelem_I4,
                                AgilOperation.Stelem_I8,    null, //4:Hint for stelem_uint (int simulated)
                                AgilOperation.Stelem_R4,
                                AgilOperation.Stelem_R8,    null  //5:Hint for stelem_real
                              ),
        #endregion
        #region Locate
        /// 从数组的指定下标上取出元素的地址。
        Locate         = SmilOperation.of("Locate",
                                AgilOperation.Ldelema,      null  //0:Hint for ldelema
                              ),
        #endregion
        #region Throw
        /// 掷出异常
        Throw               = SmilOperation.of("Throw",
                                AgilOperation.Throw,        null  //0:Hint for throw
                              ),
        #endregion
        #region Rethrow
        /// 重新掷出异常
        Rethrow             = SmilOperation.of("Rethrow",
                                AgilOperation.Rethrow,      null  //0:Hint for rethrow
                              ),
        #endregion
        #region FilterEnd
        /// 将控制从异常的 filter 子句转移回公共语言结构 (CLI) 异常处理程序。
        FilterEnd           = SmilOperation.of("FilterEnd",
                                AgilOperation.Endfilter,    null  //0:Hint for endfilter
                              ),
        #endregion
        #region FinallyEnd
        /// 将控制从异常块的 fault 或 finally 子句转移回公共语言结构 (CLI) 异常处理程序。
        FinallyEnd          = SmilOperation.of("FinallyEnd",
                                AgilOperation.Endfinally,   null  //0:Hint for endfinally
                              ),
        #endregion
        #region GoFor
        /// 退出受保护的代码区域，无条件将控制转移到特定目标指令。
        GoFor               = SmilOperation.of("GoFor",
                                AgilOperation.Leave,
                                AgilOperation.Leave_S,      null  //0:Hint for leave
                              ),
        #endregion
        #region SeeIf
        /// 比较两个值。符合条件，则将整数值 1 ((int32) 推送到计算堆栈上；否则，将 0 (int32) 推送到计算堆栈上。
        SeeIf              = SmilOperation.of("SeeIf",
                                AgilOperation.Ceq,          null, //0:Hint for ceq
                                AgilOperation.Cgt,
                                AgilOperation.Cgt_Un,       null, //1:Hint for cgt
                                AgilOperation.Clt,
                                AgilOperation.Clt_Un,       null  //2:Hint for clt
                              ),
        #endregion
        #region AssertFinite
        /// 如果值不是有限数，则引发 ArithmeticException。
        AssertFinite         = SmilOperation.of("AssertFinite",
                                AgilOperation.Ckfinite,     null  //0:Hint for ckfinite
                              ),
        #endregion
        #region Allocate
        /// 从本地动态内存池分配特定数目的字节并将第一个分配的字节的地址（瞬态指针，* 类型）推送到计算堆栈上。
        Allocate       = SmilOperation.of("Allocate",
                                AgilOperation.Localloc,     null  //0:Hint for localloc
                              ),
        #endregion
        #region Volatile
        /// 指定该地址是易失地址
        Volatile     = SmilOperation.of("Volatile",
                                AgilOperation.Volatile,     null  //0:Hint for volatile
                              ),
        #endregion
        #region Unaligned
        /// 指示当前位于计算堆栈上的地址可能没有与紧接的 ldind、stind、ldfld、stfld、ldobj、stobj、initblk 或 cpblk 指令的自然大小对齐。
        Unaligned    = SmilOperation.of("Unaligned",
                                AgilOperation.Unaligned,    null  //0:Hint for unaligned
                              ),
        #endregion
        #region Copy
        /// 将指定数目的字节从源地址复制到目标地址。
        Copy           = SmilOperation.of("Copy",
                                AgilOperation.Cpblk,        null  //0:Hint for cpblk
                              ),
        #endregion
        #region Clear
        /// 将位于特定地址的内存的指定块初始化为给定大小和初始值。
        Clear       = SmilOperation.of("Clear",
                                AgilOperation.Initblk,      null  //0:Hint for initblk
                              ),
        #endregion
        #region GivenRef
        /// 将对特定类型实例的类型化引用推送到计算堆栈上。
        GivenRef         = SmilOperation.of("GivenRef",
                                AgilOperation.Mkrefany,     null  //0:Hint for mkrefany
                              ),
        #endregion
        #region GivenType
        /// 检索嵌入在类型化引用内的类型标记。
        GivenType      = SmilOperation.of("GivenType",
                                AgilOperation.Refanytype,   null  //0:Hint for refanytype
                              ),
        #endregion
        #region AddressRef
        /// 检索嵌入在类型化引用内的地址（& 类型）。
        AddressRef    = SmilOperation.of("AddressRef",
                                AgilOperation.Refanyval,    null  //0:Hint for refanyval
                              ),
        #endregion
        #region Prefix
        /// 保留的前缀
        Prefix              = SmilOperation.of("Prefix",
                                AgilOperation.Prefixref,    null, //0:Hint for prefixref
                                AgilOperation.Prefix1,
                                AgilOperation.Prefix2,
                                AgilOperation.Prefix3,
                                AgilOperation.Prefix4,
                                AgilOperation.Prefix5,
                                AgilOperation.Prefix6,
                                AgilOperation.Prefix7,      null  //1:Hint for prefixes
                              ),
        #endregion
      };
    }
    #endregion
    #region Statics
    #region Fields
    protected static int codeCount = 0;
    #endregion
    #region Properties
    public static int CodeCount
    {
      get
      {
        return codeCount;
      }
    }
    #endregion
    #region Operators
    #endregion
    #region Methods
    public static SmilOperation GetTemplateOf(AgilOperation agil)
    {
      for (int i = 0; i < AllSmilOpcodes.Length; i++)
      {
        SmilOperation op = AllSmilOpcodes[i];

        if (op != null)
        {
          if (op.Matches(agil))
          {
            return op.Clone(agil);
          }
        }
      }
      return null;
    }
    #endregion
    #region Shortcuts
    protected static SmilOperation of(SmilOperation source, int index)
    {
      return new SmilOperation(source,index);
    }
    protected static SmilOperation of(SmilOperation source,int index,SmilOperand operand)
    {
      return new SmilOperation(source,index,operand);
    }
    protected static SmilOperation of(string name, params AgilOperation[] relativeAgils)
    {
      return of(name, codeCount++, relativeAgils);
    }
    protected static SmilOperation of(string name, int code, params AgilOperation[] relativeAgils)
    {
      return new SmilOperation(name, code, relativeAgils);
    }
    #endregion
    #endregion
    #region Fields
    protected int code = 0;
    protected int index = -1;
    protected long position = -1L;
    protected bool isRoot = false;
    protected string name = string.Empty;
    protected AgilOperation[] relativeAgils = null;
    protected SmilOperand operand = null;
    protected List<SmilOperation> forwards = null;
    #endregion
    #region Properties
    public virtual string Name
    {
      get
      {
        return this.name;
      }
    }
    public virtual int Code
    {
      get
      {
        return this.code;
      }
    }
    public virtual bool IsRoot
    {
      get
      {
        return this.isRoot;
      }
      set
      {
        this.isRoot = value;
      }
    }
    public virtual bool HasOperand
    {
      get
      {
        return this.operand != null;
      }
    }
    public virtual bool HasEffectiveOperand
    {
      get
      {
        return this.HasOperand && this.Operand.HasValueRef;
      }
    }
    public virtual SmilOperand Operand
    {
      get
      {
        return this.operand;
      }
    }
    public virtual long Position
    {
      get
      {
        return this.position;
      }
      set
      {
        this.position = value;
      }
    }
    public virtual bool HasUnderlyingAgil
    {
      get
      {
        return this.relativeAgils!=null && this.index >= 0 && this.index < this.relativeAgils.Length;
      }
    }
    public virtual AgilOperation UnderlyingAgil
    {
      get
      {
        return this.HasUnderlyingAgil ?
          this.RelativeAgils[this.index] :
          null;
      }
    }
    public virtual AgilOperation[] RelativeAgils
    {
      get
      {
        return this.relativeAgils;
      }
    }
    /// <summary>
    /// 获取堆栈压入类型序列。
    /// </summary>
    public virtual Type[] PushStackTypes
    {
      get
      {
        return this.HasUnderlyingAgil ?
          this.UnderlyingAgil.PushStack:
          null;
      }
    }
    /// <summary>
    /// 获取堆栈弹出类型序列。
    /// </summary>
    public virtual Type[] PopStackTypes
    {
      get
      {
        return this.HasUnderlyingAgil ?
          this.UnderlyingAgil.PopStack:
          null;
      }
    }
    /// <summary>
    /// 获取当前操作向前引用的操作列表，
    /// 此列表由PopStack类型辅助建立。
    /// </summary>
    public virtual List<SmilOperation> Forwards
    {
      get
      {
        return this.forwards == null ?
          this.forwards = new List<SmilOperation>() :
          this.forwards;
      }
    }
    #endregion
    #region Constructors

    protected SmilOperation(string name, int code, params AgilOperation[] relativeAgils)
    {
      this.name = name;
      this.code = code;
      this.relativeAgils = relativeAgils == null ? new AgilOperation[0] : relativeAgils;
    }
    protected SmilOperation(SmilOperation source, int index)
      : this(source, index, null)
    {
    }
    protected SmilOperation(SmilOperation source, int index, SmilOperand operand)
    {
      if (source != null)
      {
        this.index = index;
        this.name = source.name;
        this.code = source.code;
        this.relativeAgils = this.CloneAgils(source.relativeAgils);
        this.operand = operand;
      }
    }
    #endregion
    #region Methods
    #region Compare
    public virtual bool Matches(SmilOperation opcode)
    {
      return opcode != null ? this.code == opcode.Code : false;
    }
    public virtual bool Matches(AgilOperation agil)
    {
      return agil != null ? (this.GetIndexOf(agil) >= 0) : false;
    }
    public virtual int  GetIndexOf(AgilOperation agil)
    {
      if (agil != null && this.RelativeAgils!=null)
      {
        for (int index = 0; index < this.RelativeAgils.Length; index++)
        {
          AgilOperation currentAgil = this.RelativeAgils[index];

          if (currentAgil != null && currentAgil.IsOpcodeMatched(agil))
          {
            return index;
          }
        }
      }
      return -1;
    }
    public virtual int  GetIndexOf(MsilOperandCat cat)
    {
      if (this.RelativeAgils != null)
      {
        for (int index = 0; index < this.RelativeAgils.Length; index++)
        {
          AgilOperation currentAgil = this.RelativeAgils[index];

          if (currentAgil != null && currentAgil.MsilOperandCat == cat)
          {
            return index;
          }
        }
      }
      return -1;
    }
    #endregion
    #region Clone
    /// <summary>
    /// 请使用此方法Clone模板操作。
    /// </summary>
    public virtual SmilOperation Clone()
    {
      //若是模板，则设定index为0（即存在的index），否则
      //直接设定index为先前的index。
      return SmilOperation.of(this, this.HasUnderlyingAgil ? this.index : 0, this.Operand);
    }
    /// <summary>
    /// 请使用此方法从阅读器传入agil并Clone模板操作。
    /// </summary>
    /// <remarks>
    /// 若未能找到适合agil的Smil指令则返回null。
    /// </remarks>
    public virtual SmilOperation Clone(AgilOperation agil)
    {
      SmilOperation clone = null;

      if (this.Equals(agil))
      {
        int index = this.GetIndexOf(agil);
        if (index >= 0)
        {
          clone = of(this, index, SmilOperand.of(this.GetReference(agil)));

          if (clone != null)
          {
            clone.Position = agil.OperationOffset;
          }
        }
      }
      return clone;
    }
    /// <summary>
    /// 仅可以设定由Clone得到的SmilOperation
    /// 的SmilOperand。这是为了避免对基本
    /// 模板的改动而设置的屏障。
    /// </summary>
    public virtual bool SetOperand(SmilOperand operand)
    {
      if (this.HasUnderlyingAgil)
      {
        if ((this.operand = operand) != null)
        {
          Reference reference = operand.ValueRef;

          if ((this.index = this.GetIndexOf(this.GetCat(reference))) >= 0)
          {
            if (this.SetAgilOperand(this.UnderlyingAgil, reference))
            {
              return true;
            }
          }
        }
      }
      else //for fake operations.
      {
        this.operand = operand;

        return true;
      }
      return false;
    }
    protected virtual AgilOperation[] CloneAgils(AgilOperation[] source)
    {
      AgilOperation[] dest = null;

      if (source != null)
      {
        dest = new AgilOperation[source.Length];

        for (int i = 0; i < source.Length; i++)
        {
          AgilOperation op = source[i];

          dest[i] = op == null ? null : op.Clone();
        }
      }
      return dest;
    }
    #region Catagory Translations
    protected virtual bool SetAgilOperand(AgilOperation agil, Reference reference)
    {
      if (agil != null && reference!=null)
      {
        MsilOperandCat cat = agil.MsilOperandCat;

        if ((cat & MsilOperandCat.Passdown) == MsilOperandCat.Passdown)
        {
          cat &= ~MsilOperandCat.Passdown;
        }
        switch (cat)
        {
          case MsilOperandCat.Const:
            agil.Operand = (reference as ConstRef).Referenced;
            return true;
          case MsilOperandCat.Argument:
            //TODO: how to index an argument
            agil.VariableName = (reference as ParameterRef).Identifier;
            return true;
          case MsilOperandCat.Local:
            //TODO: how to index a local
            agil.VariableName = (reference as VariableRef).Identifier;
            return true;
          case MsilOperandCat.Class:
            agil.TypeOperand = (reference as TypeRef).ReflectInfo;
            return true;
          case MsilOperandCat.Field:
            agil.FieldOperand = (reference as FieldRef).ReflectInfo;
            return true;
          case MsilOperandCat.Method:
            agil.MethodOperand = (reference as MethodRef).ReflectInfo;
            return true;
          case MsilOperandCat.Null:
            //TODO: What?
            //reference = NullRef.it();
            return true;
          case MsilOperandCat.Offset:
            //TODO: How?
            agil.Labels = (reference as LabelRef).Identifier;
            return true;
          case MsilOperandCat.OffsetList:
            //TODO: How?
            return true;
          case MsilOperandCat.String:
            //TODO: How?
            agil.StringOperand = (reference as StringRef).ReflectInfo;
            return true;
          case MsilOperandCat.Token:
            agil.MemberOperand = (reference as MemberRef).MemberInfo;
            return true;
          case MsilOperandCat.Signature:
            agil.SignatureOperand = (reference as SignatureRef).ReflectInfo;
            return true;
        }
      }
      return false;
    }

    protected virtual MsilOperandCat GetCat(Reference reference)
    {
      if (reference is ConstRef)
      {
        return MsilOperandCat.Const;
      }
      else if (reference is ParameterRef)
      {
        return MsilOperandCat.Argument;
      }
      else if (reference is VariableRef)
      {
        return MsilOperandCat.Local;
      }
      else if (reference is TypeRef)
      {
        return MsilOperandCat.Class;
      }
      else if (reference is FieldRef)
      {
        return MsilOperandCat.Field;
      }
      else if (reference is MethodRef)
      {
        return MsilOperandCat.Method;
      }
      else if (reference is NullRef)
      {
        return MsilOperandCat.Null;
      }
      else if (reference is ConvertionRef)
      {
        return MsilOperandCat.Convertion | MsilOperandCat.Passdown;
      }
      else if (reference is ComparisionRef)
      {
        return MsilOperandCat.Comparision | MsilOperandCat.Passdown;
      }
      else if (reference is CalculationRef)
      {
        return MsilOperandCat.Calculation | MsilOperandCat.Passdown;
      }
      else if (reference is PrefixRef)
      {
        return MsilOperandCat.Prefix | MsilOperandCat.Passdown;
      }
      else if (reference is LabelRef)
      {
        return MsilOperandCat.Offset | MsilOperandCat.Passdown;
      }
      else if (reference is LabelsRef)
      {
        return MsilOperandCat.OffsetList;
      }
      else if (reference is StringRef)
      {
        return MsilOperandCat.String;
      }
      else if (reference is MemberRef)
      {
        return MsilOperandCat.Token;
      }
      else if (reference is SignatureRef)
      {
        return MsilOperandCat.Signature;
      }
      else
      {
        return MsilOperandCat.Ignored;
      }
    }
    protected virtual Reference GetReference(AgilOperation agil)
    {
      Reference reference = null;

      bool passdown = false;

      if (agil!= null)
      {
        MsilOperandCat cat = agil.MsilOperandCat;

        if ((cat & MsilOperandCat.Passdown) == MsilOperandCat.Passdown)
        {
          passdown = true;

          cat &= ~MsilOperandCat.Passdown;
        }

        switch (cat)
        {
          case MsilOperandCat.Const:
            reference = ConstRef.of(agil.Operand);
            break;
          case MsilOperandCat.Argument:
            reference = ParameterRef.of(agil.VariableName);
            break;
          case MsilOperandCat.Local:
            reference = VariableRef.of(agil.VariableName);
            break;
          case MsilOperandCat.Class:
            reference = TypeRef.of(agil.TypeOperand);
            break;
          case MsilOperandCat.Field:
            reference = FieldRef.of(agil.FieldOperand);
            break;
          case MsilOperandCat.Method:
            reference = MethodRef.of(agil.MethodOperand);
            break;
          case MsilOperandCat.Null:
            reference = NullRef.it();
            break;
          case MsilOperandCat.Convertion:
            reference = ConvertionRef.of(
              passdown ? AgilOperation.GetConvertion(agil) : Convertions.Unknown
            );
            break;
          case MsilOperandCat.Prefix:
            reference = PrefixRef.of(
              passdown ? AgilOperation.GetPrefix(agil) : Prefixes.Unknown
            );
            break;
          case MsilOperandCat.Comparision:
            reference = ComparisionRef.of(
              passdown ? AgilOperation.GetComparision(agil) : Comparisions.Unknown
            );
            break;
          case MsilOperandCat.Calculation:
            reference = CalculationRef.of(
              passdown ? AgilOperation.GetCalculation(agil) : Calculations.Unknown
            );
            break;
          case MsilOperandCat.Offset:
            //agil should be branch instruction or the conditon will be none.
            reference = ConditionRef.of(
              passdown ? AgilOperation.GetCondition(agil) : Conditions.Always, agil.Labels
              );
            break;
          case MsilOperandCat.OffsetList:
            reference = LabelsRef.of(agil.LabelList);
            break;
          case MsilOperandCat.String:
            reference = StringRef.of(agil.StringOperand);
            break;
          case MsilOperandCat.Token:
            reference = MemberRef.of(agil.MemberOperand);
            break;
          case MsilOperandCat.Signature:
            reference = SignatureRef.of(agil.SignatureOperand);
            break;
        }
        //patch: for fake operation which has no MsilOperandCat
        if (agil.IsFake)
        {
          //catch for now.
          if (reference == null && agil.TypeOperand != null)
          {
            reference = TypeRef.of(agil.TypeOperand);
          }
        }
      }
      return reference;
    }
    #endregion
    #endregion
    #region Format
    public virtual void LogFormatAt(OperationFormatResolver resolver)
    {
      if (resolver != null)
      {
        this.OnLogFormatAt(resolver);
      }
    }
    public virtual void SetFormatAt(OperationFormatResolver resolver, bool? isLongFormat)
    {
      if (resolver != null)
      {
        this.OnSetFormatAt(resolver, isLongFormat);
      }
    }
    protected virtual void OnLogFormatAt(OperationFormatResolver resolver)
    {

    }
    protected virtual void OnSetFormatAt(OperationFormatResolver resolver, bool? isLongFormat)
    {

    }
    #endregion
    #region Overrides
    public override string ToString()
    {
      return this.HasEffectiveOperand ?
        string.Format("{0}\t\t[{1}]", this.Name, this.Operand.ToString()) :
        string.Format("{0}", this.Name);
    }
    public override int GetHashCode()
    {
      return this.code;
    }
    public override bool Equals(object o)
    {
      if (o is SmilOperation)
      {
        return this.Matches(o as SmilOperation);
      }
      else if (o is AgilOperation)
      {
        return this.Matches(o as AgilOperation);
      }
      return false;
    }
    #endregion
    #endregion
  }
}
